#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include "z_logger.h"
#include "gpio.h"

static int _write_string(char *filename, const char *buf, size_t len) {
    int fd = open(filename, O_WRONLY);
    if (fd < 0) {
        log_errno();
        return -1;
    }

    if (write(fd, buf, len) < 0) {
        log_errno();
    }

    close(fd);

    return 0;
}

static int _write_int(char *filename, GPIO gpio) {
    char buf[16];
    sprintf(buf, "%d", gpio);
    size_t len = strlen(buf);
    return _write_string(filename, buf, len);
}

int gpio_export(GPIO gpio) {
    return _write_int("/sys/class/gpio/export", gpio);
}

int gpio_unexport(GPIO gpio) {
    return _write_int("/sys/class/gpio/unexport", gpio);
}

int gpio_open(GPIO gpio, const char *file) {
    char filename[255];
    sprintf(filename, "/sys/class/gpio/gpio%d/%s", gpio, file);

    struct stat buf;
    if (stat(filename, &buf) < 0) {
        if (gpio_export(gpio) < 0) {
            return -1;
        }
    }

    int fd = open(filename, O_WRONLY);
    if (fd < 0) {
        log_errno();
    }

    return fd;
}

_Bool gpio_get_value(int fd) {
    char buf[1] = {0};

    if (read(fd, buf, 1) < 0) {
        log_errno();
    }

    return '0' != buf[0];
}

void gpio_set_value(int fd, _Bool value) {
    char *buf = value ? "high" : "low";
    int len = value ? 4 : 3;

    if (write(fd, buf, len) < 0) {
        log_errno();
    }
}